package com.server.core;

import java.util.ArrayList;
import cmath.Convert.Convert;

import com.server.order.orderImpl;
import com.server.runtime.simulationImpl;
import com.server.runtime.vehicleImpl;
import combat.protocol.data.DoublePoint;
import combat.protocol.interfaces.OrderInt;

import combat.protocol.interfaces.TeamInt;
import combat.protocol.interfaces.VehicleInt;

public class Simulator {
    public static int simulatorTime = 0; 
    public static final int CYCLES_PER_SECOND = 4; //for entire class
    public static final int FRAME_SPLITTER = 50; //higher values make object move smoother but slower

    private static ArrayList<TeamInt> localTeams;
    private static ArrayList<VehicleInt> localVehicles;
    private static vehicleImpl localVehicle;
    private static ArrayList<OrderInt> localVehicleOrders;
    private static orderImpl currentOrder;
    
    //Main runnable loop that checks all the processes
    static Runnable runner = new Runnable() 
    {
    	public void run() {
        	while (true) {
            	try { 
            		int simTimeStart = 0;
                    int simTimeEnd = 0;
                    int simTotal = 0;
                    simTimeStart = simulatorTime;
                    
            		//Calculate movement
                    calculateMovement();        
            	
                    simTimeEnd = simulatorTime;
                    simTotal = simTimeEnd - simTimeStart;
                    
                  	//Calculate simulator time
                    if((1000/CYCLES_PER_SECOND)-simTotal > 0) {            
                    	Thread.sleep ((1000/CYCLES_PER_SECOND)-simTotal); 
            		} else {
                    	System.out.println("INFORMATION: Working ASynchron");
                    }
                } catch(InterruptedException e) {
                	System.out.println(e);
                }
            }
    	}
    };
    
    static Runnable timer = new Runnable() {
    	public void run() {
        	while (true) {
            	try {
                	Thread.sleep (1);
                    simulatorTime++;
                                                                            
                    //Increment the game time counter here
                    //simulationImpl.setGameTime(simulationImpl.getGameTime() + (1 * simulationImpl.getSimSpeed()));
                 } catch (InterruptedException e) { 
                	 System.out.println(e);
                 }
            }
       }
    };
    
    //Start simulator threads
    public static void startSimulator()
    {
    	Thread thrRunner = new Thread(runner);
        thrRunner.start();
        Thread thrTimer = new Thread(timer);
        thrTimer.start(); 
    }
    
    //Calculate new positions of the PO's
    public static void calculateMovement() {
 
    	localTeams = simulationImpl.getReference().getTeams();  	
    	//Teams loop
    	for(int i = 0; i < localTeams.size(); i++)
    	{  		
    		localVehicles = localTeams.get(i).getVehicles();
    		
    		//Vehicles loop
        	for(int j = 0; j < localVehicles.size(); j++)
        	{    		
	    		localVehicle = (vehicleImpl) localVehicles.get(j);
	    		localVehicleOrders = localVehicle.getOrders();

	    		//System.out.println("Vehicle: " + localVehicle.getName() + " Size:" + localVehicleOrders.size());	
				if(localVehicleOrders.size() != 0)
				{
					currentOrder = (orderImpl) localVehicleOrders.get(0);
					
		    		//(eerste)Order afhandelen
					switch(currentOrder.getType())
					{
		    			case ATK:
		    				//cmath > projectile fire
		    				break;
		    				
		    			case MOV:		    				
		    				//Huidige positie
		    				DoublePoint _huidigepos = localVehicle.getPosition();
		    				
		    				if(_huidigepos.nears(Convert.ToDoublePoint(currentOrder.getTarget()), 5))
		    				{
		    					//Set speed to 0
		    					localVehicle.setSpeed(0);
		    					//Remove from order list
		    					RemoveOrder(localVehicle);
		    				}
		    				else
		    				{
		    					if(!checkCollision(localVehicles,localVehicle))
		    					{
			    					localVehicle.setDirection(cmath.cmath.Position.GetNewDirection(localVehicle, currentOrder));
			    					localVehicle.setSpeed((30) * simulationImpl.getReference().getSimSpeed());
			    					localVehicle.setPosition(cmath.cmath.Position.GetNextPosition(localVehicle, currentOrder));
		    					}
		    				}
		    				break;
		    			}
					}
    			//todo, nieuwe vehicles toevoegen aan team daarna team updaten (setteam)
        	}
    	}

    	
    	
    }
    
    public static void RemoveOrder(vehicleImpl _vi)
    {
    	_vi.getOrders().remove(0);
    }
    
    //Check if any collisions have been detected
    //This method will check all physical objects for collisions
    public static boolean checkCollision(ArrayList<VehicleInt> _vehicles, vehicleImpl _subvehicle) 
    {
    	boolean _collision = false;
    	for(VehicleInt _v : _vehicles)
    	{
    		if(!_subvehicle.getName().equals(_v.getName()) && _subvehicle.getPosition().nears(_v.getPosition(), 8))    		
    		{
    			_collision = true;
    			Collide(_subvehicle, (vehicleImpl)_v);
    		}
    	}
    	
    	return _collision;
    }
    public static void Collide(vehicleImpl _v1,vehicleImpl _v2)
    {
    	_v1.setHealth(0);
    	_v2.setHealth(0);
    }

    //Move a specific vehicle to a certain point
    public static void addOrder(vehicleImpl tempVeh, int orderID, Object target, int speed) {
    	tempVeh.orderMove(orderID, target, speed);
    }

}
